﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Reflection;

namespace Common.EFExtensions
{
    /// <summary>
    /// Wichtige Extension Methods für den DataContext
    /// </summary>
    public static class DataModelExtension
    {
        /// <summary>
        /// Gibt den aktuellen Kontext zurück, in dem der User arbeiten kann (nicht 100%ig performant, laut Quelle)
        /// </summary>
        public static ObjectContext GetContext(this IEntityWithRelationships entity)
        {
            //Quelle:
            //http://blogs.msdn.com/b/alexj/archive/2009/06/08/tip-24-how-to-get-the-objectcontext-from-an-entity.aspx

            if (entity == null)
                throw new ArgumentNullException("entity");

            var relationshipManager = entity.RelationshipManager;
            var relatedEnd = relationshipManager.GetAllRelatedEnds().FirstOrDefault();

            if (relatedEnd == null)
                throw new Exception("No relationships found");

            var query = relatedEnd.CreateSourceQuery() as ObjectQuery;

            if (query == null)
                throw new Exception("The Entity is Detached");

            return query.Context;
        }

        /// <summary>
        /// Löschen der EntityItems mit Hilfe von DeleteObject aus dem aktuellen ObjectContext
        /// </summary>
        /// <returns>TRUE->Wenn Item(s) gelöscht wurden | FALSE->Wenn kein Eintrag gelöscht wurde.</returns>
        public static bool DeleteEntityItems<T>(this IEnumerable<T> entityList) where T : EntityObject
        {
            //Nuir versuchen Einträge zu löschen wenn in der Liste auch Einträge vorhanden sind.
            if (entityList.Count() > 0)
            {
                entityList.ToList().ForEach(GetContext((IEntityWithRelationships)entityList.First()).DeleteObject);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Kann verwendet werden für OrderBy in Linq Extensions
        /// http://www.codewrecks.com/blog/index.php/2009/03/21/entity-framework-dynamic-sorting-and-pagination/
        /// </summary>
        /// <typeparam name="T">Datentyp wo das Property gesucht werden soll</typeparam>
        /// <param name="field">Name des Feldes</param>
        public static Func<T, string> GetField<T>(string field)
        {
            //Beipielanwendung:
            //from eAssignmentProcess in CurrentAssignment.AssignmentProcesses.OrderBy(GetField<AssignmentProcess>("Creator"))
            PropertyInfo propertyInfo = typeof(T).GetProperty(field);
            return obj => Convert.ToString(propertyInfo.GetValue(obj, null));
        }
    }
}
